package com.wzcl.app.config;

import lombok.extern.log4j.Log4j2;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import java.util.HashMap;
import java.util.Map;

@Configuration
@Log4j2
@PropertySource({"classpath:application-config.properties"})
public class RabbitMqConfiguration {

    @Value("${spring.rabbitmq.host}")
    private String host;

    @Value("${spring.rabbitmq.port}")
    private int port;

    @Value("${spring.rabbitmq.username}")
    private String username;

    @Value("${spring.rabbitmq.password}")
    private String password;

    //交换机(direct)
    public static final String WZCL_DIRECT_EXCHANGE_NAME = "exchange_direct_wzcl";
    public static final String WZCL_DELAY_EXCHANGE_NAME = "exchange_direct_delay";
    public static final String WZCL_DEAD_LETTER_EXCHANGE_NAME = "exchange_direct_dead";
    //队列
    public static final String DIRECT_QUEUE_PAID  = "queue.order.paid";//支付通知队列
    public static final String DIRECT_QUEUE_PATH = "queue.path.send";//地址队列
    public static final String DELAY_QUEUE_ORDER = "queue.delay.order";//订单延时队列
    public static final String DEAD_QUEUE_ORDER = "queue.dead.order";//订单死信队列
    public static final String DIRECT_QUEUE_GROUP= "queue.order.group";//拼团订单处理队列

    //key
    public static final String ROUTING_KEY_ORDER_PAID = "direct.order.paid";//订单支付
    public static final String ROUTING_KEY_PATH_SEND = "direct.path.send";//发送快递
    public static final String ROUTING_KEY_ORDER_DELAY = "direct.order.delay";//订单延时过期
    public static final String ROUTING_KEY_ORDER_EXPIRED = "direct.order.expired";//订单过期
    public static final String ROUTING_KEY_ORDER_GROUP = "direct.order.group";//订单过期


    /**
     *   1.定义direct exchange，EXCHANGE_TOPIC_KAIFENG
     *   2.durable="true" rabbitmq重启的时候不需要创建新的交换机
     *   3.direct交换器相对来说比较简单，匹配规则为：如果路由键匹配，消息就被投送到相关的队列
     *     fanout交换器中没有路由键的概念，他会把消息发送到所有绑定在此交换器上面的队列中。
     *     topic交换器你采用模糊匹配路由键的原则进行转发消息到队列中
     *   key: queue在该direct-exchange中的key值，当消息发送给direct-exchange中指定key为设置值时，
     *   消息将会转发给queue参数指定的消息队列
     */
    @Bean
    public DirectExchange wzclExchange(){
        return new DirectExchange(WZCL_DIRECT_EXCHANGE_NAME,true,false);
    }

    @Bean
    public DirectExchange delayExchange(){
        return new DirectExchange(WZCL_DELAY_EXCHANGE_NAME,true,false);
    }

    @Bean
    public DirectExchange deadExchange(){
        return new DirectExchange(WZCL_DEAD_LETTER_EXCHANGE_NAME,true,false);
    }

    //声明普通队列
    @Bean
    public Queue orderQueue() {
        return new Queue(DIRECT_QUEUE_PAID,true,false,false);
    }
    @Bean
    public Queue pathQueue() {
        return new Queue(DIRECT_QUEUE_PATH,true,false,false);
    }
    @Bean
    public Queue groupQueue() {
        return new Queue(DIRECT_QUEUE_GROUP,true,false,false);
    }


    //声明延时队列
    @Bean
    public Queue delayQueue(){
        Map<String, Object> args = new HashMap<>(4);
        // x-dead-letter-exchange    这里声明当前队列绑定的死信交换机
        args.put("x-dead-letter-exchange",WZCL_DEAD_LETTER_EXCHANGE_NAME);
        // x-dead-letter-routing-key  这里声明当前队列的死信路由key
        args.put("x-dead-letter-routing-key", ROUTING_KEY_ORDER_EXPIRED);
        // x-message-ttl  声明队列的TTL
        args.put("x-message-ttl", 15 * 60 * 1000L);
        return QueueBuilder.durable(DELAY_QUEUE_ORDER).withArguments(args).build();
    }

    // 声明死信队列 用于接收延时消息
    @Bean
    public Queue orderDeadQueue(){
        return new Queue(DEAD_QUEUE_ORDER);
    }

    //绑定队列
    @Bean
    public Binding bindingOrderQueue(){
        return BindingBuilder.bind(orderQueue()).to(wzclExchange()).with(ROUTING_KEY_ORDER_PAID);
    }
    @Bean
    public Binding bindingPathQueue(){
        return BindingBuilder.bind(pathQueue()).to(wzclExchange()).with(ROUTING_KEY_PATH_SEND);
    }
    @Bean
    public Binding bindingGroupQueue(){
        return BindingBuilder.bind(groupQueue()).to(wzclExchange()).with(ROUTING_KEY_ORDER_GROUP);
    }

    //延时队列绑定关系
    @Bean
    public Binding bindingDelayQueue(){
        return BindingBuilder.bind(delayQueue()).to(delayExchange()).with(ROUTING_KEY_ORDER_DELAY);
    }

    //死信队列绑定关系
    @Bean
    public Binding bindingDeadQueue(){
        return BindingBuilder.bind(orderDeadQueue()).to(deadExchange()).with(ROUTING_KEY_ORDER_EXPIRED);
    }

    @Bean
    public CachingConnectionFactory getConnectionFactory() {
        CachingConnectionFactory factory = new CachingConnectionFactory(host,port);
        factory.setUsername(username);
        factory.setPassword(password);
        return factory;
    }

    @Bean
    public AmqpAdmin amqpAdmin() {
        return new RabbitAdmin(getConnectionFactory());
    }

    @Bean
    public RabbitTemplate rabbitTemplate() {
        return new RabbitTemplate(getConnectionFactory());
    }

}
